<!DOCTYPE html>
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
        <title>OpenLayers Cluster Strategy Example</title>
        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
        <link rel="stylesheet" href="style.css" type="text/css">
        <style type="text/css">
            #photos {
                height: 100px;
                width: 512px;
                position: relative;
                white-space: nowrap;
            }
            .shift {
                height: 25px;
                line-height: 25px;
                background-color: #fefefe;
                text-align: center;
                position: absolute;
                bottom: 10px;
                font-size: 8px;
                font-weight: bold;
                color: #696969;
                width: 25px;
            }
            #scroll-start {
                left: 0px;
            }
            #scroll-end {
                right: 0px;
            }
            #scroll {
                left: 30px;
                width: 452px;
                height: 100px;
                overflow: hidden;
                position: absolute;
                bottom: 0px;
            }
            #photos ul {
                position: absolute;
                bottom: 0px;
                padding: 0;
                margin: 0;
            }
            #photos ul.start {
                left: 0px;
            }
            #photos ul.end {
                right: 80px;
            }
            #photos ul li {
                padding: 10px;
                margin: 0;
                list-style: none;
                display: inline;
            }
            img.thumb {
                height: 30px;
            }
            img.big {
                height: 90px;
            }
        </style>
        <script src="../lib/OpenLayers.js"></script>
        <script src="Jugl.js"></script>
        <script src="animator.js"></script>
        <script type="text/javascript">
        
            var map, template;

            /**
             * A specific format for parsing Flickr API JSON responses.
             */
            OpenLayers.Format.Flickr = OpenLayers.Class(OpenLayers.Format, {
                read: function(obj) {
                    if(obj.stat === 'fail') {
                        throw new Error(
                            ['Flickr failure response (',
                             obj.code,
                             '): ',
                             obj.message].join(''));
                    }
                    if(!obj || !obj.photos ||
                       !OpenLayers.Util.isArray(obj.photos.photo)) {
                        throw new Error(
                            'Unexpected Flickr response');
                    }
                    var photos = obj.photos.photo, photo,
                        x, y, point,
                        feature, features = [];
                    for(var i=0,l=photos.length; i<l; i++) {
                        photo = photos[i];
                        x = photo.longitude;
                        y = photo.latitude;
                        point = new OpenLayers.Geometry.Point(x, y);
                        feature = new OpenLayers.Feature.Vector(point, {
                            title: photo.title,
                            img_url: photo.url_s
                        });
                        features.push(feature);
                    }
                    return features;
                }
            });

            function init() {
                map = new OpenLayers.Map('map');
                var base = new OpenLayers.Layer.OSM();

                var style = new OpenLayers.Style({
                    pointRadius: "${radius}",
                    fillColor: "#ffcc66",
                    fillOpacity: 0.8,
                    strokeColor: "#cc6633",
                    strokeWidth: 2,
                    strokeOpacity: 0.8
                }, {
                    context: {
                        radius: function(feature) {
                            return Math.min(feature.attributes.count, 7) + 3;
                        }
                    }
                });

                var photos = new OpenLayers.Layer.Vector("Photos", {
                    projection: "EPSG:4326",
                    strategies: [
                        new OpenLayers.Strategy.Fixed(),
                        new OpenLayers.Strategy.Cluster()
                    ],
                    protocol: new OpenLayers.Protocol.Script({
                        url: "http://api.flickr.com/services/rest",
                        params: {
                            api_key: 'b5e8c0e287e678671c3d8b2c0f3ced85',
                            format: 'json',
                            method: 'flickr.photos.search',
                            extras: 'geo,url_s',
                            per_page: 150,
                            page: 1,
                            bbox: [-180, -90, 180, 90]
                        },
                        callbackKey: 'jsoncallback',
                        format: new OpenLayers.Format.Flickr()
                    }),
                    styleMap: new OpenLayers.StyleMap({
                        "default": style,
                        "select": {
                            fillColor: "#8aeeef",
                            strokeColor: "#32a8a9"
                        }
                    })
                });
                
                var select = new OpenLayers.Control.SelectFeature(
                    photos, {hover: true}
                );
                map.addControl(select);
                select.activate();
                photos.events.on({"featureselected": display});

                map.addLayers([base, photos]);
                map.setCenter(new OpenLayers.LonLat(0, 0), 1);
                
                // template setup
                template = new jugl.Template("template");

            }
            
            function display(event) {
                // clear previous photo list and create new one
                document.getElementById("photos").innerHTML = "";
                var node = template.process({
                    context: {features: event.feature.cluster},
                    clone: true,
                    parent: document.getElementById("photos")
                });
                // set up forward/rewind
                var forward = Animator.apply(document.getElementById("list"), ["start", "end"], {duration: 1500});
                document.getElementById("scroll-end").onmouseover = function() {forward.seekTo(1)};
                document.getElementById("scroll-end").onmouseout = function() {forward.seekTo(forward.state)};
                document.getElementById("scroll-start").onmouseover = function() {forward.seekTo(0)};
                document.getElementById("scroll-start").onmouseout = function() {forward.seekTo(forward.state)};
                // set up photo zoom
                for(var i=0; i<event.feature.cluster.length; ++i) {
                    listen(document.getElementById("link-" + i), Animator.apply(document.getElementById("photo-" + i), ["thumb", "big"]));
                }
            }
            
            function listen(el, anim) {
                el.onmouseover = function() {anim.seekTo(1)};
                el.onmouseout = function() {anim.seekTo(0)};
            }
            
        </script>
    </head>
    <body onload="init()">
        <h1 id="title">Cluster Strategy Example</h1>
        <div id="tags">
            vector, feature, stylemap, cluster, strategy, flickr, script
        </div>         
        <p id="shortdesc">
            Uses a cluster strategy to render points representing clusters of features.
        </p>
        <div id="map" class="smallmap"></div>
        <div id="docs">
            <p>The Cluster strategy lets you display points representing clusters
            of features within some pixel distance.</p>
            <p>This particular example uses the <a
                href="http://www.flickr.com/services/api/">Flickr API.</a></p>
        </div>
        <div id="photos"></div>
        <p>Hover over a cluster on the map to see the photos it includes.</p>
        <div style="display: none;">
            <div id="template">
                <div class="shift" id="scroll-start">&lt;&lt;</div>
                <div id="scroll">
                    <ul id="list" class="start">
                        <li jugl:repeat="feature features">
                            <a jugl:attributes="href feature.attributes.img_url;
                                                id 'link-' + repeat.feature.index"
                               target="_blank">
                                <img jugl:attributes="src feature.attributes.img_url;
                                                      title feature.attributes.title;
                                                      id 'photo-' + repeat.feature.index"
                                     class="thumb" />
                            </a>
                        </li>
                    </ul>
                </div>
                <div class="shift" id="scroll-end">&gt;&gt;</div>
            </div>
        </div>
    </body>
</html>
